package contrl

import (
	"core/env"
	"core/graylog"
	"core/utils"
	"db"
	"fmt"
	"time"

	"github.com/gin-gonic/gin"
)

type UserContrl struct{}

type UserGotFreeGrassRes struct {
	GoldNum        int `json:"goldNum"`
	GotFreeGrassAt int64
}

func (*UserContrl) GotFreeGrass(c *gin.Context) (res interface{}, e Error) {
	sign := GetSign(c)
	if !db.Lock(sign.Uid) {
		return nil, GenErrorMsg("您太快了，稍微慢些哦")
	}
	defer db.Unlock(sign.Uid)

	u, err := db.LoadByUID(sign.Uid, true)
	if err != nil {
		return nil, GenError(err)
	}
	if u.GotFreeGrassAt.After(time.Now()) {
		return UserGotFreeGrassRes{GoldNum: u.Grass, GotFreeGrassAt: u.GotFreeGrassAt.Unix()},
			GenErrorMsg(fmt.Sprintf("%d小时后才能领取哦", env.Config.FreeGrassCoolHour))
	}
	u.Grass++
	share := GetBool(c, "share")
	if share {
		u.Grass++
	}
	u.GotFreeGrassAt = time.Now().Add(time.Hour * time.Duration(env.Config.FreeGrassCoolHour))
	err = u.Save(db.FieldGotFreeGrassAt, db.FieldGrass)
	if err != nil {
		return nil, GenErrorMsg("领取失败，请刷新后重试")
	}

	go graylog.Info("领取免费四叶草", graylog.M{
		"playerId":       u.UID,
		"name":           u.Name,
		"grass":          u.Grass,
		"gotFreeGrassAt": u.GotFreeGrassAt,
		"isShare":        fmt.Sprintf("%t", share),
	})

	res = UserGotFreeGrassRes{
		GoldNum:        u.Grass,
		GotFreeGrassAt: u.GotFreeGrassAt.Unix(),
	}
	return
}

type UserUnlockRes struct {
	GoldNum int `json:"goldNum"`
	BasicLevel
}

func (*UserContrl) Unlock(c *gin.Context) (res interface{}, e Error) {
	menuId := GetInt(c, "menu_id")
	level := GetInt(c, "level")
	if menuId < 1 || menuId > len(env.MenuList) {
		return nil, GenErrorMsg("参数错误menu_id")
	}
	if level < 1 || level > len(env.MenuList[menuId-1].JigsawListById) {
		return nil, GenErrorMsg("参数错误level")
	}
	sign := GetSign(c)
	if !db.Lock(sign.Uid) {
		return nil, GenErrorMsg("您太快了，稍微慢些哦")
	}
	defer db.Unlock(sign.Uid)

	u, err := db.LoadByUID(sign.Uid, true)
	if err != nil {
		return nil, GenError(err)
	}
	if u.Level[menuId] == nil {
		u.Level[menuId] = make(map[int]db.LevelDetail)
	}
	detail := u.Level[menuId][level]
	if detail.Unlock {
		return nil, GenErrorMsg("请不要重复解锁")
	}

	conf := env.MenuList[menuId-1].JigsawListById[level-1]
	if u.Grass < conf.GoldNum {
		return nil, GenErrorMsg("四叶草不足")
	}
	u.Grass -= conf.GoldNum
	err = u.Save(db.FieldGrass)
	if err != nil {
		return nil, GenError(err)
	}
	detail.Unlock = true
	err = u.SaveLevel(menuId, level, &detail)
	if err != nil {
		u.Grass += conf.GoldNum
		err = u.Save(db.FieldGrass)
		return nil, GenError(err)
	}

	go graylog.Info("解锁拼图", graylog.M{
		"playerId": u.UID,
		"name":     u.Name,
		"menuId":   menuId,
		"levelId":  level,
		"grass":    u.Grass,
		"levels":   fmt.Sprintf("%+v", u.Level),
	})
	res = UserUnlockRes{
		GoldNum:    u.Grass,
		BasicLevel: genLevels(u),
	}
	return
}

type UserFinishRes struct {
	HasCardPkg bool `json:"hasCardPkg"`
	GoldNum    int  `json:"goldNum"`
	AddWater   int
	Water      int
	BeforeRankInfo
	BasicLevel
}

// 完成拼图
func (*UserContrl) Finish(c *gin.Context) (res interface{}, e Error) {
	menuId := GetInt(c, "menu_id")
	level := GetInt(c, "level")
	if menuId < 1 || menuId > len(env.MenuList) {
		return nil, GenErrorMsg("参数错误menu_id")
	}
	if level < 1 || level > len(env.MenuList[menuId-1].JigsawListById) {
		return nil, GenErrorMsg("参数错误level")
	}
	sign := GetSign(c)
	if !db.Lock(sign.Uid) {
		return nil, GenErrorMsg("您太快了，稍微慢些哦")
	}
	defer db.Unlock(sign.Uid)

	u, err := db.LoadByUID(sign.Uid, true)
	if err != nil {
		return nil, GenError(err)
	}
	if u.Level[menuId] == nil {
		return nil, GenErrorMsg("请先解锁拼图")
	}
	detail, found := u.Level[menuId][level]
	if !found {
		return nil, GenErrorMsg("请先解锁拼图哦")
	}

	conf := env.MenuList[menuId-1].JigsawListById[level-1]
	hasCardPkg := true
	var addWater int
	if detail.FinishNum > 0 {
		hasCardPkg = env.HasCardPkg()
	} else if detail.FinishNum == 0 {
		u.Water += conf.Water
		addWater = conf.Water
	}
	u.FinishLevelAt = time.Now()

	err = u.Save(db.FieldFinishLevelAt, db.FieldWater)
	if err != nil {
		return nil, GenError(err)
	}
	detail.FinishNum++
	err = u.SaveLevel(menuId, level, &detail)
	if err != nil {
		return nil, GenError(err)
	}

	go graylog.Info("完成拼图", graylog.M{
		"playerId":    u.UID,
		"name":        u.Name,
		"menuId":      menuId,
		"levelId":     level,
		"water":       u.Water,
		"finishCount": detail.FinishNum,
		"levels":      fmt.Sprintf("%+v", u.Level),
	})
	res = UserFinishRes{
		HasCardPkg:     hasCardPkg,
		GoldNum:        u.Grass,
		Water:          u.Water,
		AddWater:       addWater,
		BeforeRankInfo: updateRankAndLoadBeforePlayer(u.UID, u.Water, addWater),
		BasicLevel:     genLevels(u),
	}
	return
}

func (*UserContrl) SaveBasicInfo(c *gin.Context) (res interface{}, e Error) {
	name := c.GetString("nickName")
	headImg := c.GetString("avatarUrl")
	gender := GetInt(c, "gender")
	age := GetInt(c, "age")
	province := c.GetString("province")
	city := c.GetString("city")

	sign := GetSign(c)
	u, err := db.LoadByUID(sign.Uid, true)
	if err != nil {
		return nil, GenError(err)
	}
	u.Authorize = true
	saveFields := []string{db.FieldAuthorize}
	if name != "" {
		u.Name = name
		saveFields = append(saveFields, db.FieldName)
	}
	if headImg != "" {
		u.HeadImg = headImg
		saveFields = append(saveFields, db.FieldHeadImg)
	}
	if gender > 0 {
		u.Gender = gender
		saveFields = append(saveFields, db.FieldGender)
	}
	if age > 0 {
		u.Age = age
		saveFields = append(saveFields, db.FieldAge)
	}
	if province != "" {
		u.Province = province
		saveFields = append(saveFields, db.FieldProvince)
	}
	if city != "" {
		u.City = city
		saveFields = append(saveFields, db.FieldCity)
	}
	err = u.Save(saveFields...)
	if err != nil {
		return nil, GenError(err)
	}

	go graylog.Info("更新用户基本信息", graylog.M{
		"playerId": u.UID,
		"name":     u.Name,
		"headImg":  u.HeadImg,
		"gender":   gender,
		"age":      age,
	})
	res = "ok"
	return
}

// 完成并分享拼图
func (*UserContrl) ShareByFinish(c *gin.Context) (res interface{}, e Error) {
	sign := GetSign(c)
	if !db.Lock(sign.Uid) {
		return nil, GenErrorMsg("您太快了，稍微慢些哦")
	}
	defer db.Unlock(sign.Uid)

	u, err := db.LoadByUID(sign.Uid, true)
	if err != nil {
		return nil, GenError(err)
	}
	if u.GotCardPkgAt.After(u.FinishLevelAt) {
		return nil, GenErrorMsg("您没有可用卡包了哦，请先完成拼图")
	}
	if time.Now().After(u.FinishLevelAt.Add(time.Minute * 5)) {
		return nil, GenErrorMsg("您没有可用卡包，请先完成拼图")
	}
	u.Grass += 1
	u.GotCardPkgAt = time.Now()
	err = u.Save(db.FieldGrass, db.FieldGotCardPkgAt)
	if err != nil {
		return nil, GenError(err)
	}

	go graylog.Info("完成并分享拼图", graylog.M{
		"playerId": u.UID,
		"grass":    u.Grass,
	})
	res = UserUnlockRes{
		GoldNum: u.Grass,
	}
	return
}

type UserGotVideoRewardResponse struct {
	GoldNum          int `json:"goldNum"`
	WatchVideoRemain int
}

func (*UserContrl) GotVideoReward(c *gin.Context) (res interface{}, e Error) {
	sign := GetSign(c)
	if !db.Lock(sign.Uid) {
		return nil, GenErrorMsg("您太快了，稍微慢些哦")
	}
	defer db.Unlock(sign.Uid)

	u, err := db.LoadByUID(sign.Uid, true)
	if err != nil {
		return nil, GenError(err)
	}
	if u.WatchVideoCount >= env.Config.WatchVideoLimit {
		return nil, GenErrorMsg("今日看视频次数已用尽")
	}

	u.WatchVideoCount++
	u.Grass++
	err = u.Save(db.FieldWatchVideoCount, db.FieldGrass)
	if err != nil {
		return nil, GenError(err)
	}

	go graylog.Info("领取看视频奖励", graylog.M{
		"playerId":        u.UID,
		"name":            u.Name,
		"grass":           u.Grass,
		"watchVideoCount": u.WatchVideoCount,
	})
	res = UserGotVideoRewardResponse{
		GoldNum:          u.Grass,
		WatchVideoRemain: env.Config.WatchVideoLimit - u.WatchVideoCount,
	}
	return
}

type UserInviteRewardLog struct {
	Uid   int64
	Grass int
}
type UserGotInviteRewardResponse struct {
	InviteList []InvitePlayer
	GoldNum    int `json:"goldNum"`
	RewardLogs []UserInviteRewardLog
}

func (*UserContrl) GotInviteReward(c *gin.Context) (res interface{}, e Error) {
	sign := GetSign(c)
	if !db.Lock(sign.Uid) {
		return nil, GenErrorMsg("您太快了，稍微慢些哦")
	}
	defer db.Unlock(sign.Uid)
	u, err := db.LoadByUID(sign.Uid, true)
	if err != nil {
		return nil, GenError(err)
	}

	oldGrass := u.Grass
	logs := make([]UserInviteRewardLog, 0)
	var count int
	for k, v := range u.Invitees {
		if count >= env.Config.InviteLimit+10 {
			break
		}
		if !v.GotReward {
			conf := env.InviteConfs[k]
			u.Invitees[k].GotReward = true
			u.Grass += conf.Grass
			logs = append(logs, UserInviteRewardLog{Uid: v.UID, Grass: conf.Grass})
		}
		count++
	}
	if len(logs) == 0 {
		return nil, GenErrorMsg("没有奖励可以领取")
	}
	err = u.Save(db.FieldGrass, db.FieldInvitee)
	if err != nil {
		return nil, GenError(err)
	}

	go graylog.Info("领取邀请奖励", graylog.M{
		"playerId":   u.UID,
		"name":       u.Name,
		"oldGrass":   oldGrass,
		"newGrass":   u.Grass,
		"rewardLogs": fmt.Sprintf("%+v", logs),
	})

	res = UserGotInviteRewardResponse{
		InviteList: genInviteList(u),
		GoldNum:    u.Grass,
		RewardLogs: logs,
	}
	return
}

type UserUploadPicInfo struct {
	Name     string `json:"name"`
	Status   int    `json:"status"`
	Love     int    `json:"love"`
	CreateAt int64  `json:"create_at"`
}

type UserMyHomeRes struct {
	Name         string              `json:"name"`
	UID          int64               `json:"uid"`
	Love         int                 `json:"love"`
	MyUploadPics []UserUploadPicInfo `json:"my_upload_pics"`
}

func (*UserContrl) MyHome(c *gin.Context) (res interface{}, e Error) {
	sign := GetSign(c)
	u, err := db.LoadByUID(sign.Uid, true)
	if err != nil {
		return nil, GenError(err)
	}

	picUploadAccess, err := db.LoadPicUploadAccessIfNotExist(u.UID)
	if err != nil {
		return nil, GenError(err)
	}
	picUpload, err := db.LoadPicUploadIfNotExist(u.UID)
	if err != nil {
		return nil, GenError(err)
	}

	list := make([]UserUploadPicInfo, 0)
	totalLove := 0
	for _, pic := range picUploadAccess.List {
		if pic.ID <= 0 {
			utils.Error("picUploadAccess,pic.ID <= 0", pic)
			continue
		}
		item := UserUploadPicInfo{
			Name:     pic.Name,
			Status:   pic.Status,
			CreateAt: pic.CreateAt,
		}
		picConf, _ := db.LoadPicConfig(pic.ConfId)
		if picConf != nil {
			item.Love = picConf.Love
			totalLove += picConf.Love
		}
		list = append(list, item)
	}
	for _, pic := range picUpload.List {
		if pic.ID <= 0 {
			utils.Error("picUpload,pic.ID <= 0", pic)
			continue
		}
		list = append(list, UserUploadPicInfo{
			Name:     pic.Name,
			Status:   pic.Status,
			CreateAt: pic.CreateAt,
		})
	}

	res = UserMyHomeRes{
		Name:         u.Name,
		UID:          u.UID,
		Love:         totalLove,
		MyUploadPics: list,
	}
	return
}
